#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <sstream> // 用于拆分日期字符串
#include <string>
#include <vector>

using namespace std;

// 交易结构体（保持不变）
struct Transaction {
    string date;     // 格式：YYYY-MM-DD
    double amount;   // 金额（正数）
    string category; // 类别（如餐饮、工资）
    string remarks;  // 备注
    bool isIncome;   // true=收入，false=支出
};

// 月度统计结构体（新增）
struct MonthlyStats {
    double totalIncome = 0.0;            // 当月总收入
    double totalExpense = 0.0;           // 当月总支出
    map<string, double> categoryIncome;  // 当月各收入类别金额
    map<string, double> categoryExpense; // 当月各支出类别金额
};

class BillManager {
  private:
    vector<Transaction> transactions;   // 所有交易记录
    map<string, double> categoryBudget; // 分类预算（键：类别，值：预算金额）

    // 辅助函数：从日期字符串提取年月（YYYY-MM）（新增）
    string extractYearMonth(const string &date) {
        // 简单验证日期格式（至少8个字符：YYYY-MM）
        if (date.size() < 7 || date[4] != '-' || date[7] != '-') {
            return "无效日期";
        }
        return date.substr(0, 7); // 截取前7位，得到YYYY-MM
    }

  public:
    // ---------------------- 原有功能（保持不变） ----------------------
    void recordIncome() {
        Transaction trans;
        trans.isIncome = true;
        cout << "请输入收入信息：" << endl;
        cout << "日期（YYYY-MM-DD）：";
        cin >> trans.date;
        cout << "金额：";
        cin >> trans.amount;
        while (trans.amount <= 0) {
            cout << "收入金额必须为正数，请重新输入金额：";
            cin >> trans.amount;
        }
        cout << "类别（如工资、奖金等）：";
        cin >> trans.category;
        cout << "备注：";
        cin.ignore();
        getline(cin, trans.remarks);
        transactions.push_back(trans);
        cout << "收入已成功记录！" << endl;
    }

    void recordExpense() {
        Transaction trans;
        trans.isIncome = false;
        cout << "请输入支出信息：" << endl;
        cout << "日期（YYYY-MM-DD）：";
        cin >> trans.date;
        cout << "金额：";
        cin >> trans.amount;
        while (trans.amount <= 0) {
            cout << "支出金额必须为正数，请重新输入金额：";
            cin >> trans.amount;
        }
        cout << "类别（如餐饮、交通、购物等）：";
        cin >> trans.category;
        cout << "备注：";
        cin.ignore();
        getline(cin, trans.remarks);
        transactions.push_back(trans);
        cout << "支出已成功记录！" << endl;
    }

    void viewAllTransactions() {
        if (transactions.empty()) {
            cout << "暂无账单记录！" << endl;
            return;
        }

        double totalIncome = 0;
        double totalExpense = 0;

        cout << endl << "===================== 所有账单记录 =====================" << endl;
        cout << left << setw(12) << "日期" << setw(10) << "类型" << setw(10) << "金额" << setw(15) << "类别"
             << "备注" << endl;
        cout << "--------------------------------------------------------" << endl;

        for (const auto &trans : transactions) {
            cout << left << setw(12) << trans.date;
            cout << setw(10) << (trans.isIncome ? "收入" : "支出");
            cout << setw(10) << fixed << setprecision(2) << trans.amount;
            cout << setw(15) << trans.category;
            cout << trans.remarks << endl;

            if (trans.isIncome)
                totalIncome += trans.amount;
            else
                totalExpense += trans.amount;
        }

        cout << "--------------------------------------------------------" << endl;
        cout << "总收入：" << fixed << setprecision(2) << totalIncome << " 元" << endl;
        cout << "总支出：" << fixed << setprecision(2) << totalExpense << " 元" << endl;
        cout << "结余：" << fixed << setprecision(2) << (totalIncome - totalExpense) << " 元" << endl;
        cout << "========================================================" << endl << endl;
    }

    void queryTransactions() {
        if (transactions.empty()) {
            cout << "暂无账单记录可查询！" << endl;
            return;
        }

        int queryOption;
        cout << endl << "查询方式：" << endl;
        cout << "1. 按日期查询" << endl;
        cout << "2. 按类别查询" << endl;
        cout << "请选择查询方式：";
        cin >> queryOption;
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        vector<Transaction> results;
        string keyword;

        if (queryOption == 1) {
            cout << "请输入要查询的日期（YYYY-MM-DD）：";
            getline(cin, keyword);
            for (const auto &trans : transactions) {
                if (trans.date == keyword)
                    results.push_back(trans);
            }
        } else if (queryOption == 2) {
            cout << "请输入要查询的类别：";
            getline(cin, keyword);
            for (const auto &trans : transactions) {
                if (trans.category == keyword)
                    results.push_back(trans);
            }
        } else {
            cout << "无效的查询方式！" << endl;
            return;
        }

        if (results.empty()) {
            cout << "未找到匹配的账单记录！" << endl;
            return;
        }

        double totalIncome = 0, totalExpense = 0;
        cout << endl << "===================== 查询结果 =====================" << endl;
        cout << left << setw(12) << "日期" << setw(10) << "类型" << setw(10) << "金额" << setw(15) << "类别" << "备注"
             << endl;
        cout << "---------------------------------------------------" << endl;

        for (const auto &trans : results) {
            cout << left << setw(12) << trans.date << setw(10) << (trans.isIncome ? "收入" : "支出") << setw(10)
                 << fixed << setprecision(2) << trans.amount << setw(15) << trans.category << trans.remarks << endl;
            if (trans.isIncome)
                totalIncome += trans.amount;
            else
                totalExpense += trans.amount;
        }

        cout << "---------------------------------------------------" << endl;
        cout << "查询结果总收入：" << fixed << setprecision(2) << totalIncome << " 元" << endl;
        cout << "查询结果总支出：" << fixed << setprecision(2) << totalExpense << " 元" << endl;
        cout << "查询结果结余：" << fixed << setprecision(2) << (totalIncome - totalExpense) << " 元" << endl;
        cout << "===================================================" << endl << endl;
    }

    // ---------------------- 新增：预算管理功能 ----------------------
    // 1. 设置分类预算
    void setCategoryBudget() {
        string category;
        double budget;

        cout << endl << "===================== 设置分类预算 =====================" << endl;
        cout << "请输入预算类别（如餐饮、交通、购物）：";
        cin >> category;
        cout << "请输入该类别的预算金额（正数）：";
        cin >> budget;

        // 验证预算金额为正
        while (budget <= 0) {
            cout << "预算金额必须为正数，请重新输入：";
            cin >> budget;
        }

        // 覆盖或新增预算
        categoryBudget[category] = budget;
        cout << "已成功设置【" << category << "】类别的预算：" << fixed << setprecision(2) << budget << " 元" << endl;
        cout << "========================================================" << endl << endl;
    }

    // 2. 查看预算使用情况（按类别统计已支出/剩余预算）
    void viewBudgetUsage() {
        if (categoryBudget.empty()) {
            cout << "暂无已设置的预算，请先设置分类预算！" << endl;
            return;
        }

        // 统计各支出类别的已使用金额
        map<string, double> usedAmount;
        for (const auto &trans : transactions) {
            if (!trans.isIncome) { // 只统计支出
                usedAmount[trans.category] += trans.amount;
            }
        }

        cout << endl << "===================== 预算使用情况 =====================" << endl;
        cout << left << setw(15) << "预算类别" << setw(12) << "预算金额" << setw(12) << "已使用金额" << setw(12)
             << "剩余金额"
             << "状态" << endl;
        cout << "--------------------------------------------------------" << endl;

        for (const auto &[category, budget] : categoryBudget) {
            double used = usedAmount.count(category) ? usedAmount[category] : 0.0;
            double remaining = budget - used;

            cout << left << setw(15) << category;
            cout << setw(12) << fixed << setprecision(2) << budget;
            cout << setw(12) << fixed << setprecision(2) << used;
            cout << setw(12) << fixed << setprecision(2) << remaining;
            // 显示状态（未超支/超支）
            if (remaining >= 0)
                cout << "正常（未超支）" << endl;
            else
                cout << "⚠️  超支（超支" << fixed << setprecision(2) << -remaining << "元）" << endl;
        }
        cout << "========================================================" << endl << endl;
    }

    // ---------------------- 新增：月度统计功能 ----------------------
    void monthlyStatistics() {
        if (transactions.empty()) {
            cout << "暂无账单记录，无法进行月度统计！" << endl;
            return;
        }

        // 按“YYYY-MM”分组统计月度数据
        map<string, MonthlyStats> monthlyData;
        for (const auto &trans : transactions) {
            string yearMonth = extractYearMonth(trans.date);
            if (yearMonth == "无效日期") {
                cout << "警告：交易日期【" << trans.date << "】格式错误，已跳过统计" << endl;
                continue;
            }

            auto &stats = monthlyData[yearMonth];
            if (trans.isIncome) {
                stats.totalIncome += trans.amount;
                stats.categoryIncome[trans.category] += trans.amount;
            } else {
                stats.totalExpense += trans.amount;
                stats.categoryExpense[trans.category] += trans.amount;
            }
        }

        // 选择要查看的月份
        cout << endl << "===================== 月度统计 =====================" << endl;
        cout << "已有统计数据的月份：" << endl;
        int idx = 1;
        vector<string> months;
        for (const auto &[yearMonth, _] : monthlyData) {
            cout << idx++ << ". " << yearMonth << endl;
            months.push_back(yearMonth);
        }

        cout << "请输入要查看的月份序号：";
        int monthIdx;
        cin >> monthIdx;
        if (monthIdx < 1 || monthIdx > months.size()) {
            cout << "无效的月份序号！" << endl;
            return;
        }

        // 显示选中月份的统计详情
        string selectedMonth = months[monthIdx - 1];
        auto &stats = monthlyData[selectedMonth];
        cout << endl << "--------------------- " << selectedMonth << " 统计详情 ---------------------" << endl;

        // 1. 月度收支汇总
        cout << "1. 月度收支汇总：" << endl;
        cout << "   总收入：" << fixed << setprecision(2) << stats.totalIncome << " 元" << endl;
        cout << "   总支出：" << fixed << setprecision(2) << stats.totalExpense << " 元" << endl;
        cout << "   月度结余：" << fixed << setprecision(2) << (stats.totalIncome - stats.totalExpense) << " 元"
             << endl;
        // 新增：计算并显示收支比例（如果总收入不为0）
        if (stats.totalIncome > 0) {
            double expenseRatio = (stats.totalExpense / stats.totalIncome) * 100;
            cout << "   支出占收入比例：" << fixed << setprecision(1) << expenseRatio << "%" << endl;
        }
        // 2. 收入类别明细
        cout << "\n2. 收入类别明细：" << endl;
        if (stats.categoryIncome.empty()) {
            cout << "   本月无收入记录" << endl;
        } else {
            for (const auto &[category, amount] : stats.categoryIncome) {
                cout << "   " << left << setw(10) << category << "：" << fixed << setprecision(2) << amount << " 元"
                     << endl;
            }
        }

        // 3. 支出类别明细（关联预算）
        cout << "\n3. 支出类别明细（含预算对比）：" << endl;
        if (stats.categoryExpense.empty()) {
            cout << "   本月无支出记录" << endl;
        } else {
            cout << "   " << left << setw(10) << "类别" << setw(12) << "支出金额" << setw(12) << "预算金额" << "状态"
                 << endl;
            cout << "   ------------------------------------------------" << endl;
            for (const auto &[category, amount] : stats.categoryExpense) {
                cout << "   " << left << setw(10) << category << setw(12) << fixed << setprecision(2) << amount;
                if (categoryBudget.count(category)) {
                    double budget = categoryBudget[category];
                    double remaining = budget - amount;
                    cout << setw(12) << budget;
                    if (remaining >= 0)
                        cout << "正常（剩" << fixed << setprecision(2) << remaining << "元）" << endl;
                    else
                        cout << "⚠️  超支（超" << fixed << setprecision(2) << -remaining << "元）" << endl;
                } else {
                    cout << setw(12) << "未设置" << "无预算" << endl;
                }
            }
        }
        cout << "========================================================" << endl << endl;
    }
};

// ---------------------- 主函数（更新菜单选项） ----------------------
int main() {
    BillManager billManager;
    int option;

    while (true) {
        cout << "=================================" << endl;
        cout << "欢迎使用个人账单管理系统" << endl;
        cout << "=================================" << endl;
        cout << "请选择操作：" << endl;
        cout << "1. 记录收入" << endl;
        cout << "2. 记录支出" << endl;
        cout << "3. 查看所有账单" << endl;
        cout << "4. 查询账单" << endl;
        cout << "5. 设置分类预算" << endl;     // 新增
        cout << "6. 查看预算使用情况" << endl; // 新增
        cout << "7. 月度统计" << endl;         // 新增
        cout << "8. 退出系统" << endl;         // 原5改为8

        cout << "请输入选项序号：";
        cin >> option;

        // 输入错误处理（保持不变）
        if (cin.fail()) {
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            cout << "输入错误，请输入数字选项！" << endl;
            continue;
        }

        // 菜单逻辑（新增5/6/7选项）
        switch (option) {
        case 1:
            billManager.recordIncome();
            break;
        case 2:
            billManager.recordExpense();
            break;
        case 3:
            billManager.viewAllTransactions();
            break;
        case 4:
            billManager.queryTransactions();
            break;
        case 5:
            billManager.setCategoryBudget();
            break; // 新增
        case 6:
            billManager.viewBudgetUsage();
            break; // 新增
        case 7:
            billManager.monthlyStatistics();
            break; // 新增
        case 8:
            cout << "感谢使用个人账单管理系统，再见！" << endl;
            return 0;
        default:
            cout << "无效的选项，请重新选择！" << endl;
        }

        cout << "按任意键返回主菜单...";
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cin.get();
    }

    return 0;
}